﻿using UnityEngine;

namespace AI.Graph {


    public abstract class Condition : CollapsibleNode {

#region Fields

        private static NodeColors s_colors = new NodeColors (new Color32 (255, 170, 120, 255), new Color32 (178, 120, 84, 255), new Color32 (140, 94, 66, 255));

        [SerializeField, HideInInspector]
        [Port (Direction.Input, Capacity.Multi, "Input")]
        private ConnectionPort m_input = null;

        [SerializeField, HideInInspector]
        [Port (Direction.Output, Capacity.Multi, "True")]
        private ConnectionPort m_outputTrue = null;

        [SerializeField, HideInInspector]
        [Port (Direction.Output, Capacity.Multi, "False")]
        private ConnectionPort m_outputFalse = null;

#endregion


#region Properties

        internal override NodeColors colors {
            get { return s_colors; }
        }

        internal ConnectionPort input {
            get { return m_input; }
        }

        internal ConnectionPort outputTrue {
            get { return m_outputTrue; }
        }

        internal ConnectionPort outputFalse {
            get { return m_outputFalse; }
        }

#endregion


        /// <summary>
        /// Decides which states is the next one.  
        /// </summary>
        /// <param name="aiBehaviour">the connected AIBehaviour.</param>
        /// <returns>Returns the next state.</returns>
        public State Decide (AIBehaviour aiBehaviour) {
            bool decision = OnDecide (aiBehaviour);
            aiBehaviour.Log (this, $"Decision was: {decision}");

            if (decision) {
                return Decide (aiBehaviour, outputTrue.connectedPorts);
            }
            else {
                return Decide (aiBehaviour, outputFalse.connectedPorts);
            }
        }


        State Decide (AIBehaviour aiBehaviour, ConnectionPort[] connectedPorts) {
            foreach (ConnectionPort port in connectedPorts) {
                Node node = port.node;

                if (node.IsTypeOf<State> ()) {
                    return node as State;
                }

                if (node.IsTypeOf<Condition> ()) {
                    Condition condition = (Condition) node;
                    State state = condition.Decide (aiBehaviour);

                    if (state != null) {
                        return state;
                    }
                }
            }

            return null;
        }


        /// <summary>
        /// Check if the condition is true.
        /// </summary>
        /// <param name="aiBehaviour">The connected AIBehaviour.</param>
        /// <returns>Returns true or false depending on the condition.</returns>
        protected abstract bool OnDecide (AIBehaviour aiBehaviour);


        /// <summary>
        /// Deep clone with the given original Node.
        /// </summary>
        internal override void Copy (AIControllerSerializer serializer, Node originalNode) {
            base.Copy (serializer, originalNode);
            Condition original = (Condition) originalNode;

            m_input = serializer.GetCopyOf (original.m_input);
            m_outputTrue = serializer.GetCopyOf (original.m_outputTrue);
            m_outputFalse = serializer.GetCopyOf (original.m_outputFalse);
        }

    }


}